package mailserver.server;

import java.sql.SQLException;
import java.util.ArrayList;
import mailcommon.entities.*;
import mailcommon.helpers.DateHelper;
import mailserver.server.exceptions.*;
import mailserver.sql.*;

public class ClientService {

    private MailAddress address;
    private boolean logged;

    public ClientService() {
        logged = false;
    }

    public void registration(User user, String address)
            throws ServerException, SQLException {
        if (!logged) {
            UserService.getInstance().add(user);
            int userId = UserService.getInstance().getId(user);
            this.address = new MailAddress(address, DateHelper.getInstance().now(), userId);
            AddressService.getInstance().add(this.address);
        } else {
            throw new UserLoggedInException();
        }
    }

    /**
     * Bind address for this client connection.
     *
     * @param address
     * @throws SQLException
     * @throws MailAddressNotExistsException in case of this address not
     * registed.
     * @throws UserLoggedInException in case of user already logged.
     */
    public void login(String address)
            throws SQLException, MailAddressNotExistsException, UserLoggedInException {
        if (!logged) {
            if (!AddressService.getInstance().exists(address)) {
                throw new MailAddressNotExistsException();
            } else {
                this.address = AddressService.getInstance().select(
                        "address = " + "\"" + address + "\"").get(0);
                logged = true;
            }
        } else {
            throw new UserLoggedInException();
        }
    }

    public Letter readLetter(int id)
            throws SQLException, ServerException {
        if (logged) {
            Letter letter;
            try {
                letter = LetterService.getInstance().select("id = " + id).get(0);
                if (!letter.getRecipientAddress()
                        .equalsIgnoreCase(
                        this.address.getUniqueAddres())) {
                    throw new LetterNotExistsException();
                }
                LetterService.getInstance().markRead(id);
            } catch (ArrayIndexOutOfBoundsException ex) {
                throw new LetterNotExistsException();
            }
            return letter;
        } else {
            throw new UserNotLoggedInException();
        }
    }

    public void sendLetter(String recipient, String subject, String body)
            throws SQLException, UserNotLoggedInException {
        if (logged) {
            LetterService.getInstance().add(new Letter(
                    address.getUniqueAddres(), recipient,
                    DateHelper.getInstance().now(),
                    subject, body));
        } else {
            throw new UserNotLoggedInException();
        }
    }

    public ArrayList<Letter> getLetters(boolean all)
            throws SQLException, UserNotLoggedInException {
        if (logged) {
            if (all) {
                return LetterService.getInstance().selectByRecipient(
                        address.getUniqueAddres());
            } else {
                return LetterService.getInstance().selectByRecipientUnread(
                        address.getUniqueAddres());
            }
        } else {
            throw new UserNotLoggedInException();
        }
    }

    public void logout()
            throws UserNotLoggedInException {
        if (logged) {
            logged = false;
        } else {
            throw new UserNotLoggedInException();
        }
    }

    public boolean isLogged() {
        return logged;
    }
}
